/**
 * Trabalho 3 de Programacao Concorrente.
 * Prof. Dr. Julio Estrella
 * 
 * Resolucao de sistemas lineares.
 * 
 * Grupo 07 - Turma B
 * Fabio de Albuquerque Dela Antonio 6792558
 * Leonardo Henrique Omoto 6793160
 * Pedro Paulo Canto Martucci 6793100
 * 
 * matrix.c
 */

#include <geral.h>
#include <matrix.h>

/**
 * Aloca Sistema
 */
Sist * alocaSistema(int n_vars) {

    Sist * ret = (Sist *) malloc(sizeof(Sist));
    
    if(ret == NULL) {
        printf("Erro: Memoria insuficiente para alocacao do sistema!\n");
        exit(1);
    }

    double ** matriz;
    int i, j;
    
    /* Aloca linhas... */
    matriz = (double **) malloc(n_vars*sizeof(double *));
    
    if(matriz == NULL) {
        printf("Erro: Memoria insuficiente para alocacao do sistema!\n");
        exit(1);
    }
    
    /* Aloca colunas... */
    for(i = 0; i < n_vars; i++) {
        matriz[i] = (double *) malloc((n_vars+1)*sizeof(double));
        if(matriz[i] == NULL) {
            printf("Erro: Memoria insuficiente para alocacao do sistema!\n");
            exit(1);
        }
    }
    
    /* Zera matriz */
    for(i = 0; i < n_vars; i++) {
        for(j = 0; j < n_vars+1; j++) {
            matriz[i][j] = 0;
        }
    }

    ret->matrix = matriz;
    ret->J_ORDER = n_vars;

    return ret;
}

/**
 * Carrega Sistema do arquivo "sistema.dat"
 */
Sist * carregaSistema(char * filename) {

    /* Aloca sistema. */
    Sist * ret;
    int n_vars;
    int row_test;
    double error;
    int iter;
    
    int i, j;
    
    FILE * in = fopen(filename, "r");
    
    if(in == NULL) {
        fprintf(stderr, "Impossivel carregar arquivo do sistema.\n");
        exit(1);
    }
    
    /* Carrega cabecalho (sem checar entradas) */
    fscanf(in, "%d", &n_vars);
    fscanf(in, "%d", &row_test);
    fscanf(in, "%lf", &error);
    fscanf(in, "%d", &iter);
    
    ret = alocaSistema(n_vars);

    /* Recebe dados da matriz A (sem checagens).*/

    for(i = 0; i < ret->J_ORDER; i++) {
        for(j = 0; j < (ret->J_ORDER); j++) {
            fscanf(in, "%lf", &(ret->matrix[i][j]));
        }
    }
    
    /* Recebe dados da matriz B */
    for(i = 0; i < ret->J_ORDER; i++)
        fscanf(in, "%lf", &(ret->matrix[i][ret->J_ORDER]));
    
    
    /* Fecha arquivo. */
    fclose(in);
    
    /* Atribui demais informacoes ao sistema */
    ret->J_ROW_TEST = row_test;
    ret->J_ERROR = error;
    ret->J_ITE_MAX = iter;
    
    /* Retorna sistema. */        
    return ret;
    
}

/**
 * Imprime Sistema
 */
void imprimeSistema(Sist *sis) {
    
    int i, j;
    
    for(i = 0; i < sis->J_ORDER; i++) {
        for(j = 0; j < (sis->J_ORDER+1); j++) {
            printf("%lf ",sis->matrix[i][j]);
        }
        printf("\n");
    }
}

/**
 * Imprime Matriz
 */
void imprimeMatriz(Sist *sis) {
    
    int i, j;
    
    for(i = 0; i < sis->J_ORDER; i++) {
        for(j = 0; j < (sis->J_ORDER); j++) {
            printf("%lf ",sis->matrix[i][j]);
        }
        printf("\n");
    }
}

/**
 * Limpa Sistema
 */
void limpaSistema(Sist *sis) {
    
    int i;
    
    for(i = 0; i < sis->J_ORDER; i++)
        free(sis->matrix[i]);
    
    free(sis->matrix);
    
    sis->J_ORDER = 0;
}
